﻿using System;

namespace Achievements
{
    public class TimedAchievement : Achievement, ITimedAchievement
    {
        public const string StartTimePropertyString = "StartTime";
        public const string EndTimePropertyString = "EndTime";
        public const string ElapsedTimePropertyString = "ElapsedTime";
        public const string AchievementTimePropertyString = "AchievementTime";

        #region Implementation of ITimedAchievement

        /// <summary>
        /// Starts the timer.
        /// </summary>
        public void StartTimer()
        {
            ResetTimer();
            StartTime = DateTime.Now;
        }

        /// <summary>
        /// Resets the timer.
        /// </summary>
        public void ResetTimer()
        {
            StartTime = null;
            EndTime = null;
        }

        /// <summary>
        /// Marks this attempt as failed. Calls ResetTimer(). StartTimer must be used for another attempt.
        /// </summary>
        public void Failed()
        {
            ResetTimer();
        }

        /// <summary>
        /// Marks this attempt as completed successfully. If the attempt took less time then the AchievementTime, the Achievement will be unlocked.
        /// </summary>
        public void CompletedSuccessfully()
        {
            if (ElapsedTime <= AchievementTime)
            {
                UnlockAchievement();
            }
            else
            {
                Failed();
            }
            EndTime = DateTime.Now;
        }

        #endregion

        #region Implementation of ITimedAchievement

        private TimeSpan? _achievementTime;
        private DateTime? _endTime;
        private DateTime? _startTime;

        /// <summary>
        /// Gets the start time.
        /// </summary>
        public DateTime? StartTime
        {
            get { return _startTime; }
            set
            {
                if (_startTime != value)
                {
                    _startTime = value;
                    RaisePropertyChanged(StartTimePropertyString);
                    RaisePropertyChanged(ElapsedTimePropertyString);
                }
            }
        }

        /// <summary>
        /// Gets the end time.
        /// </summary>
        public DateTime? EndTime
        {
            get { return _endTime; }
            set
            {
                if (_endTime != value)
                {
                    _endTime = value;
                    RaisePropertyChanged(EndTimePropertyString);
                    RaisePropertyChanged(ElapsedTimePropertyString);
                }
            }
        }

        /// <summary>
        /// Gets the elapsed time.
        /// </summary>
        public TimeSpan? ElapsedTime
        {
            get
            {
                if (StartTime.HasValue)
                    return DateTime.Now.Subtract(StartTime.Value);
                return null;
            }
        }

        /// <summary>
        /// Gets the achievement time.
        /// </summary>
        public TimeSpan AchievementTime
        {
            get
            {
                if (_achievementTime.HasValue)
                    return _achievementTime.Value;
                return TimeSpan.Zero;
            }
            set
            {
                if (_achievementTime.HasValue)
                {
                    throw new ArgumentException("Cannot reinitialize AchievementTime");
                }
                _achievementTime = value;
            }
        }

        #endregion
    }
}